package com.megvii.koala.components;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.GradientDrawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.megvii.koala.R;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.process.BitmapProcessor;

/**
 * Created by linyue on 15/12/22.
 */
public class ImageViewEx extends RelativeLayout
{
    public static final Bitmap.Config[] configs = new Bitmap.Config[]{Bitmap.Config.ALPHA_8, Bitmap.Config.RGB_565, Bitmap.Config.ARGB_4444, Bitmap.Config.ARGB_8888};

    public static final int DEFAULT_BORDER_COLOR = 0xffffffff;

    protected ImageView image;

    protected AutoRatioImageview ratioImage;

    protected RelativeLayout backgound;

    protected TextView textView;

    private Bitmap.Config config;

    private Style style;

    private int resOnloading;

    private int resOnFail;

    private int resOnEmpty;

    private boolean autoRatio;

    private String defaultText;

    private int borderColor = DEFAULT_BORDER_COLOR;

    private float borderWidthPercent = 0;

    private float textSize;

    public ImageViewEx(Context context)
    {
        super(context);
        init(null);
    }

    public ImageViewEx(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init(attrs);
    }

    public ImageViewEx(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        init(attrs);
    }

    public static Bitmap toRoundCornerWithBorder(Bitmap bitmap, int borderColor,
            float borderWidthPercent)
    {
        float width = bitmap.getWidth();
        float height = bitmap.getHeight();
        float outSize = width < height ? width : height;
        float borderWidth = outSize * borderWidthPercent;
        Bitmap roundCorner = toRoundCorner(bitmap);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(borderColor);
        paint.setStrokeWidth(borderWidth);
        paint.setStyle(Paint.Style.STROKE);
        Canvas canvas = new Canvas(roundCorner);
        canvas.drawCircle(outSize / 2, outSize / 2, outSize / 2 - borderWidth / 2 + 0.5f, paint);
        return roundCorner;
    }

    /**
     * 把bitmap切成圆
     */
    public static Bitmap toRoundCorner(Bitmap bitmap)
    {
        Rect centRect = null;
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        int outSize = width < height ? width : height;

        if (width > height)
        {
            centRect = new Rect((width - outSize) / 2, 0, width - (width - outSize) / 2, outSize);
        }
        else
        {
            centRect = new Rect(0, (height - outSize) / 2, outSize,
                    height - ((height - outSize) / 2));
        }

        Bitmap retBitmap = Bitmap.createBitmap(outSize, outSize, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(retBitmap);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, outSize, outSize);
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawCircle(outSize / 2, outSize / 2, outSize / 2, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, centRect, rect, paint);
        return retBitmap;
    }

    //    private void setNullUrlBackground()
    //    {
    //        image.setVisibility(View.GONE);
    //        ratioImage.setVisibility(View.GONE);
    //        backgound.setVisibility(View.VISIBLE);
    //        textView.setVisibility(View.VISIBLE);
    //        GradientDrawable drawable = (GradientDrawable) backgound.getBackground();
    //        int color = ColorUtil.hashStringToARGBColor(defaultText, 255);
    //        int revertColor = ColorUtil.getRevertColor(color);
    //        drawable.setColor(color);
    //        textView.setTextColor(revertColor);
    //    }

    private void setNullUrlBackground()
    {
        image.setVisibility(View.GONE);
        ratioImage.setVisibility(View.GONE);
        backgound.setVisibility(View.VISIBLE);
        textView.setVisibility(View.VISIBLE);
        GradientDrawable drawable = (GradientDrawable) backgound.getBackground();
        int bgColor = 0xff77a2cd;
        int textColor = 0xffffffff;
        drawable.setColor(bgColor);
        textView.setTextColor(textColor);
    }

    public void loadImage(String iconUrl)
    {
        if (resOnEmpty <= 0 && (iconUrl == null || iconUrl.isEmpty()))
        {
            setNullUrlBackground();
        }
        else
        {
            updateImageVisiblility();
            backgound.setVisibility(View.GONE);
            textView.setVisibility(View.GONE);
            DisplayImageOptions iOptions = new DisplayImageOptions.Builder().cacheInMemory(true)
                    .cacheOnDisk(true).considerExifParams(true).bitmapConfig(config)
                    .showImageOnLoading(resOnloading).showImageForEmptyUri(resOnEmpty)
                    .showImageOnFail(resOnFail).postProcessor(new BitmapProcessor()
                    {
                        @Override
                        public Bitmap process(Bitmap bitmap)
                        {
                            switch (style)
                            {
                                case ROUND:
                                    return toRoundCorner(bitmap);
                                case ROUND_BORDER:
                                    return toRoundCornerWithBorder(bitmap, borderColor,
                                            borderWidthPercent);
                                case NOT_ROUND:
                                default:
                                    return bitmap;
                            }
                        }
                    }).build();
            ImageLoader.getInstance().displayImage(iconUrl, getRealImage(), iOptions);
        }
    }

    public void loadImage(String iconUrl, String textOnNullUrl)
    {
        setTextOnNullUrl(textOnNullUrl);
        loadImage(iconUrl);
    }

    public void loadResImage(int resId)
    {
        if (resId <= 0)
        {
            setNullUrlBackground();
        }
        else
        {
            updateImageVisiblility();
            backgound.setVisibility(View.GONE);
            textView.setVisibility(View.GONE);
            getRealImage().setImageResource(resId);
        }
    }

    private void init(AttributeSet attrs)
    {
        inflate(getContext(), R.layout.imageex_layout, this);
        this.image = (ImageView) findViewById(R.id.imageex_layout_image);
        this.ratioImage = (AutoRatioImageview) findViewById(R.id.imageex_layout_ratioImage);
        this.backgound = (RelativeLayout) findViewById(R.id.imageex_layout_bg);
        this.textView = (TextView) findViewById(R.id.imageex_layout_text);
        if (attrs != null)
        {
            TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.ImageExView);
            setStyle(Style.getEnum(array.getInt(R.styleable.ImageExView_style, 0)));
            setConfig(configs[array.getInt(R.styleable.ImageExView_config, 0)]);
            setResOnLoading(array.getResourceId(R.styleable.ImageExView_src_on_loading, 0));
            setResOnFail(array.getResourceId(R.styleable.ImageExView_src_on_fail, 0));
            setResOnEmpty(array.getResourceId(R.styleable.ImageExView_src_on_empty, 0));
            setAutoRatio(array.getBoolean(R.styleable.ImageExView_auto_ratio, false));
            setTextOnNullUrl(array.getString(R.styleable.ImageExView_text));
            setTextSize(array.getDimension(R.styleable.ImageExView_text_size, 18));
            setBorderColor(
                    array.getColor(R.styleable.ImageExView_border_color, DEFAULT_BORDER_COLOR));
            setBorderWidthPercent(
                    array.getFloat(R.styleable.ImageExView_border_width_percent, 0.05f));
        }
        if (resOnEmpty <= 0)
        {
            loadImage(null);
        }
        else
        {
            loadResImage(resOnEmpty);
        }
    }

    private ImageView getRealImage()
    {
        return autoRatio ? ratioImage : image;
    }

    public void setConfig(Bitmap.Config config)
    {
        this.config = config;
    }

    public void setStyle(Style style)
    {
        this.style = style;
    }

    public void setResOnLoading(int resOnloading)
    {
        this.resOnloading = resOnloading;
    }

    public void setResOnFail(int resOnFail)
    {
        this.resOnFail = resOnFail;
    }

    public void setResOnEmpty(int resOnEmpty)
    {
        this.resOnEmpty = resOnEmpty;
    }

    public void setAutoRatio(boolean autoRatio)
    {
        this.autoRatio = autoRatio;
        updateImageVisiblility();
    }

    public void setBorderColor(int color)
    {
        this.borderColor = color;
    }

    public void setBorderWidthPercent(float borderWidthPercent)
    {
        this.borderWidthPercent = borderWidthPercent;
    }

    private void updateImageVisiblility()
    {
        image.setVisibility(autoRatio ? View.GONE : View.VISIBLE);
        ratioImage.setVisibility(autoRatio ? View.VISIBLE : View.GONE);
    }

    public void setTextOnNullUrl(String text)
    {
        this.defaultText = text;
        if (text == null || defaultText.isEmpty())
        {
            textView.setText(text);
        }
        else
        {
            String firstLetter = text.substring(0, 1);
            textView.setText(firstLetter);
        }
    }

    public void setTextSize(float size)
    {
        textSize = size;
        textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
    }

    public enum Style
    {
        NOT_ROUND, ROUND, ROUND_BORDER;

        static Style getEnum(int ordinal)
        {
            return Style.values()[ordinal];
        }
    }
}
